package ig.finanzas;

import ig.util.ConexionServer;
import ig.util.ejb.IGBean;
import ig.util.excepciones.DatoInvalidoExcepcion;
import ig.util.excepciones.LogicaExcepcion;
//import java.io.FileNotFoundException;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Properties;
import javax.ejb.FinderException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * Define la forma en que se paga utilizando una tasa.
 * Como tasa de referencia no puede especificarse una curva cero cupon.
 * @author lfgarcia
 */
public class TasaPago implements RangoTiempo {

	/** Representa la forma de una tasa fija simple */
	public static final byte FORMA_SIMPLE = 0;
	/** Representa la forma Tasa + spread  */
	public static final byte FORMA_ADICION = 1;
	/** Representa la forma Tasa * spread */
	public static final byte FORMA_PRODUCTO = 2;
	/** Representa la forma (1+Tasa)(1+spread) */
	public static final byte FORMA_MIXTA = 3;	
	
	/**
	 * Especifica la forma en que se operan los factores.
	 * @uml.property  name="forma"
	 */
	private byte forma;
	/**
	 * @uml.property  name="spread"
	 */
	private double spread;
	/**
	 * Fecha a partir de la cual aplica la tasa de pago
	 * @uml.property  name="fechaInicio"
	 */
	private Date fechaInicio;
	/**
	 * Fecha hasta la cual aplica la tasa de pago
	 * @uml.property  name="fechaFin"
	 */
	private Date fechaFin;
	/**
	 * @uml.property  name="tasareferenciaPK"
	 * @uml.associationEnd  
	 */
	private TasaPK tasareferenciaPK;
	/**
	 * @uml.property  name="modalidadspread"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Modalidad modalidadspread;
	/**
	 * @uml.property  name="modalidadpago"
	 * @uml.associationEnd  multiplicity="(1 1)"
	 */
	private Modalidad modalidadpago;
	/**
	 * Especifica si se liquida con la tasa vigente al fin de periodo,  en caso contrario se asume que se liquida con la tasa de principio  de periodo.
	 * @uml.property  name="liquidaFinPeriodo"
	 */
	private boolean liquidaFinPeriodo;	

	/**
	 * Constructor de una tasa de pago simple, es decir, una tasa de pago fija.
	 * @param spread
	 * @param fechaInicio
	 * @param fechaFin
	 * @param modalidadtasa
	 * @param nominalmodalidadspread
	 * @param modalidadpago
	 * @param nominalmodalidadpago
	 * @throws DatoInvalidoExcepcion Si la fecha de inicio o fin son nulas, o si las modalidades
	 * especificadas no poseen valores validos.
	 */
	public TasaPago( double spread, Date fechaInicio, Date fechaFin, 
			String modalidadtasa, boolean nominalmodalidadspread, 
			String modalidadpago, boolean nominalmodalidadpago )throws DatoInvalidoExcepcion{
		
		if (fechaInicio == null)
			throw new DatoInvalidoExcepcion("Fecha de inicio nula.");
		
		if (fechaFin == null)
			throw new DatoInvalidoExcepcion("Fecha fin nula.");
		
		this.forma = FORMA_SIMPLE;
		this.spread = spread;
		this.fechaInicio = fechaInicio;
		this.fechaFin = fechaFin;
		this.modalidadspread = new Modalidad(modalidadtasa, nominalmodalidadspread);
		this.modalidadpago = new Modalidad(modalidadpago, nominalmodalidadpago);
		this.liquidaFinPeriodo = false;
	}

	/**
	 * Constructor de una tasa de pago compleja. Utiliza una tasadereferencia y un spread.
	 * @param forma
	 * @param spread
	 * @param fechaInicio
	 * @param fechaFin
	 * @param tasareferenciaPK
	 * @param modalidadtasa
	 * @param nominalmodalidadspread
	 * @param modalidadpago
	 * @param nominalmodalidadpago
	 * @param liquidaFinPeriodo
	 * @throws DatoInvalidoExcepcion Si la fecha de inicio o fin son nulas, o si la forma 
	 * de la tasa de pago no es valida, o si las modalidades especificadas no poseen valores
	 * validos.
	 */
	public TasaPago( byte forma, double spread, Date fechaInicio, Date fechaFin, TasaPK tasareferenciaPK, 
			String modalidadtasa, boolean nominalmodalidadspread, 
			String modalidadpago, boolean nominalmodalidadpago, boolean liquidaFinPeriodo ) 
	throws DatoInvalidoExcepcion{
		
		if (!( forma == FORMA_ADICION || forma == FORMA_PRODUCTO 
				|| forma == FORMA_MIXTA ))
			throw new DatoInvalidoExcepcion("Valor para la forma de la tasa de pago no valido");
		
		if (fechaInicio == null)
			throw new DatoInvalidoExcepcion("Fecha de inicio nula.");
		
		if (fechaFin == null)
			throw new DatoInvalidoExcepcion("Fecha fin nula.");
		
		this.forma = forma;
		this.spread = spread;
		this.fechaInicio = fechaInicio;
		this.fechaFin = fechaFin;
		this.tasareferenciaPK = tasareferenciaPK;
		this.modalidadspread = new Modalidad(modalidadtasa, nominalmodalidadspread);
		this.modalidadpago = new Modalidad(modalidadpago, nominalmodalidadpago);
		this.liquidaFinPeriodo = liquidaFinPeriodo;		
	}
	
	/**
	 * @return  Returns the fechaInicio.
	 * @uml.property  name="fechaInicio"
	 */
	public Date getFechaInicio(){
		return fechaInicio;
	}
	
	/**
	 * @return  Returns the fechaFin.
	 * @uml.property  name="fechaFin"
	 */
	public Date getFechaFin(){
		return fechaFin;
	}
	
	/**
	 * Obtiene el valor nominal especifico de la tasa de pago en un periodo.
	 * @param fechaAnalisis Fecha en la que se realiza el analisis.
	 * @param fechaUltimoFlujo Fecha del ultimo pago de flujos.
	 * @return
	 * @throws FinderException Si no fue posible encontrar la tasa
	 * @throws DatoInvalidoExcepcion Si alguna de las fechas especificadas es nula, 
	 * @throws LogicaExcepcion Si no se puede calcular el valor vigente de la tasa o si el
	 * valor calculado es imaginario
	 */
	public double tasaNominalPeriodo(Date fechaAnalisis, Date fechaUltimoFlujo) 
	throws FinderException, DatoInvalidoExcepcion, LogicaExcepcion{
		
		if (fechaAnalisis==null)
			throw new DatoInvalidoExcepcion("La fecha de analisis es nula.");
		
		if (fechaUltimoFlujo==null)
			throw new DatoInvalidoExcepcion("La fecha del ultimo flujo es nula.");
			
		
		double valortasa = 0;
		if (tasareferenciaPK!=null){
			Properties prop = new Properties();
			prop.put( Context.INITIAL_CONTEXT_FACTORY, IGBean.INITIAL_CONTEXT_FACTORY);
			String Sockec = new ConexionServer().getSocketServer();
			prop.put( Context.PROVIDER_URL, Sockec);
			
			try {
				InitialContext ctx = new InitialContext(prop);

				TasaHome home = (TasaHome)ctx.lookup("ig.finanzas.Tasa");
				Tasa tasa = home.findByPrimaryKey(tasareferenciaPK);
				
				if (liquidaFinPeriodo)
					valortasa = tasa.obtenerValorVigenteA(fechaAnalisis, 0);
				else
					valortasa = tasa.obtenerValorVigenteA(fechaUltimoFlujo, 0);
				Modalidad modalidadTasa = tasa.getModalidadTasa();
				
				//cambio la expresion de la tasa a la expresion del spread(modalidadspread)
				valortasa = LibreriaOperacionesFinancieras.conversionTasas( 
						valortasa, modalidadTasa, modalidadspread);
			} catch (RemoteException e) {
			} catch (NamingException e) {
				 throw new FinderException(e.toString());
			}

			if (forma == FORMA_ADICION)
				valortasa = valortasa + spread/100;
			if (forma == FORMA_PRODUCTO)
				valortasa = valortasa * spread/100;
			if (forma == FORMA_MIXTA)
				valortasa = (1+valortasa)*(1+spread/100);
		}else
			valortasa = spread/100;
		
		double valortasanominal = LibreriaOperacionesFinancieras.conversionTasas(
				valortasa, modalidadspread, 
				new Modalidad(modalidadpago.getPeriodo(), modalidadpago.getModo(), true));
		
		return valortasanominal;
	}
	
}
